package cn.lazydong.dbproperties;

import cn.lazydong.dbproperties.config.DbPropertyBeanCollect;
import cn.lazydong.dbproperties.config.DbPropertySourcesEnvironment;
import cn.lazydong.dbproperties.config.SpringValue;
import org.springframework.core.env.PropertySource;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author HeLingdong
 */
public class DbPropertiesUtil {

    // 这里加一个是否 忽略空值，不忽略的话就直接抛异常

    public static void addPropertySource(String key, Object value) {
        DbPropertySourcesEnvironment.PROPERTIES.put(key, value);
    }

    public static boolean isExistSysPropertySource(String key) {
        for (PropertySource<?> propertySource : DbPropertySourcesEnvironment.propertySources) {
            if (propertySource.getName().equals(DbPropertySourcesEnvironment.db_PropertySourcesName)) {
                continue;
            }
            if (propertySource.containsProperty(key)) {
                return true;
            }
        }
        return false;
    }

    public static Object getValueFromDb(String key) {
        PropertySource<?> propertySource = DbPropertySourcesEnvironment.propertySources.get(DbPropertySourcesEnvironment.db_PropertySourcesName);
        assert propertySource != null;
        return propertySource.getProperty(key);
    }

    public static Object getValueFromSystem(String key) {
        for (PropertySource<?> propertySource : DbPropertySourcesEnvironment.propertySources) {
            if(DbPropertySourcesEnvironment.db_PropertySourcesName.equals(propertySource.getName())){
                continue;
            }
            if(propertySource.containsProperty(key)){
                return propertySource.getProperty(key);
            }
        }
        return null;
    }

    public static Object getValueFromAll(String key) {
        Object valueFromSystem = getValueFromSystem(key);
        if(valueFromSystem != null){
            return valueFromSystem;
        }
        return getValueFromDb(key);
    }


    @SuppressWarnings("unchecked")
    public static Map<String, Object> getAllValueFromDb() {
        PropertySource<?> propertySource = DbPropertySourcesEnvironment.propertySources.get(DbPropertySourcesEnvironment.db_PropertySourcesName);
        assert propertySource != null;
        return (Map<String, Object>) propertySource.getSource();
    }

    public static void refresh(String key, Object value) {
        doRefresh(key, value);
    }

    public static void refresh(Map<String, Object> keyValue) {
        if (keyValue.isEmpty()) {
            return;
        }
        for (Map.Entry<String, Object> entry : keyValue.entrySet()) {
            doRefresh(entry.getKey(), entry.getValue());
        }
    }


    /**
     * 更新数值
     */
    private static void doRefresh(String key, Object value) {
        List<SpringValue> springValues = DbPropertyBeanCollect.ALL_VALUE_BEAN.get(key);
        if (springValues == null || springValues.isEmpty()) {
            return;
        }
        for (SpringValue springValue : springValues) {
            try {
                springValue.getDeclaredField().setAccessible(true);
                String valueOf = String.valueOf(value);
                Field declaredField = springValue.getDeclaredField();
                if (declaredField.getType() == String.class) {
                    springValue.getDeclaredField().set(springValue.getBean(), valueOf);
                } else if (declaredField.getType() == Integer.class) {
                    springValue.getDeclaredField().set(springValue.getBean(), Integer.parseInt(valueOf));
                } else if (declaredField.getType() == Long.class) {
                    springValue.getDeclaredField().set(springValue.getBean(), Long.parseLong(valueOf));
                } else if (declaredField.getType() == Short.class) {
                    springValue.getDeclaredField().set(springValue.getBean(), Short.parseShort(valueOf));
                } else if (declaredField.getType() == Boolean.class) {
                    springValue.getDeclaredField().set(springValue.getBean(), Boolean.parseBoolean(valueOf));
                } else if (declaredField.getType() == Float.class) {
                    springValue.getDeclaredField().set(springValue.getBean(), Float.parseFloat(valueOf));
                } else {
                    throw new RuntimeException("Unsupported type:" + declaredField.getType().getTypeName());
                }
                springValue.getDeclaredField().setAccessible(springValue.getAccessible());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
